//
//  File.swift
//  
//
//  Created by Ink on 2024/2/17.
//

import UIKit
import RxSwift
import NSObject_Rx

extension Reactive where Base: UIControl {
    
    public var tap: ControlEvent<Void> {
        controlEvent(.touchUpInside)
    }
}

private class ClosureSleeve {
    
    var closure: ZMHandler?
    
    init(_ mClosure: ZMHandler?) {
        closure = mClosure
    }
    
    @objc func invoke() {
        closure?()
    }
}

// MARK: -  UIControl event
extension UIControl {
        
    private typealias HandlerMap = [UInt: ClosureSleeve]
    
    fileprivate struct AssociatedKeys {
        static let touchHandlerMapKey = "UIControl_touchHandlerMapKey"
    }
        
    private var handlerMap: HandlerMap {
        set { mUtilMap[AssociatedKeys.touchHandlerMapKey] = newValue }
        get {
            guard let value = mUtilMap[AssociatedKeys.touchHandlerMapKey] as? HandlerMap else {
                let tMap = HandlerMap()
                self.handlerMap = tMap
                return tMap
            }
            return value
        }
    }
    
    @discardableResult
    public func addHandler(for controlEvents: UIControl.Event = .touchUpInside,customInterval:TimeInterval? = nil, _ action: ZMHandler?) -> Self {
        if let customInterval = customInterval {
            self.customInterval = customInterval
        }
        let sleeve = ClosureSleeve(action)
        handlerMap[controlEvents.rawValue] = sleeve
        if controlEvents == .touchUpInside {
            rx.tap.subscribe(onNext: {
                [weak sleeve] in
                sleeve?.invoke()
            }).disposed(by: rx.disposeBag)
        } else {
            addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
        }
        
        return self
    }
    
    @discardableResult
    public func removeHandler(for controlEvents: UIControl.Event = .allEvents) -> Self {
        let sleeve = handlerMap[controlEvents.rawValue]
        handlerMap[controlEvents.rawValue] = nil
        removeTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
        return self
    }
}

private extension UIControl.AssociatedKeys {
    static var defaultInterval:TimeInterval = 0.5
    static var customInterval = getZMKey()
    static var ignoreInterval = getZMKey()
}

extension UIControl {
    
    public class func swizzleSendAction() {
        DispatchQueue.once("UIControlSwizzleSendAction") {
            _ = UIControl.swizzle_sendAction
        }
    }
    
    private static let swizzle_sendAction = Swizzle(UIControl.self) {
//        #selector(sendAction) <-> #selector(mySendAction)
        #selector(UIControl.sendAction(_:to:for:)) <-> #selector(UIControl.mySendAction(_:to:for:))
    }
    
    // 自定义时间间隔
    var customInterval: TimeInterval {
        get {
            mUtilMap[AssociatedKeys.customInterval] as? TimeInterval ?? AssociatedKeys.defaultInterval
        }
        set {
            mUtilMap[AssociatedKeys.customInterval] = newValue
        }
    }

    // 是否忽略间隔
    var ignoreInterval: Bool {
        get {
            mUtilMap[AssociatedKeys.ignoreInterval] as? Bool ?? (self is UIButton ? false : true)
        }
        set {
            mUtilMap[AssociatedKeys.ignoreInterval] = newValue
        }
    }

    @objc private dynamic func mySendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
        if !ignoreInterval {
            isUserInteractionEnabled = false
            DispatchQueue.main.after(customInterval) { [weak self] in
                self?.isUserInteractionEnabled = true
            }
        }
        mySendAction(action, to: target, for: event)
    }
}
